﻿// pomian.cpp: 定义应用程序的入口点。
//

#include "pomian.h"
#include "Tokenizer.h"

using namespace std;
using namespace Pomian;

int main()
{
	std::string filename = "example.pomian";
	Tokenizer *tokenizer = new Tokenizer(filename);

	Grammar* grammar = createPomian();
	AstNode* ast = grammar->parse(tokenizer);
//    ast = grammar->parse(tokenizer);
	int a = 0;
	return 0;
}

namespace Pomian
{
    Grammar* createPomian()
    {
        Grammar* primary = Grammar::grammar();
        Grammar* factor = createFactor(primary);
        Grammar* expr = Grammar::grammar();
        primary = createPrimary(primary, expr);
        expr = createExpr(expr, factor);
        Grammar* block = Grammar::grammar();
        Grammar* simple = expr;
        Grammar* statement = createStatement(expr, block, simple);
        Grammar* lineEnd = createLineEnd();
        block = createBlock(block, statement, lineEnd);
        return createProgram(statement, lineEnd);
        //return block;
    }

    Grammar* createStatement(Grammar* expr, Grammar* block, Grammar* simple)
    {
        Grammar* statement = Grammar::grammar();

        Grammar* elseStatement = Grammar::grammar();
        elseStatement->sequence({ createKeyword("else"), block }, [](const std::vector<AstNode*>& nodes)->AstNode* {
            return nodes.at(1);
        });
        Grammar* ifStatement = Grammar::grammar();
        ifStatement->sequence({ createKeyword("if"), expr, block, Grammar::grammar()->option(elseStatement)}, [](const std::vector<AstNode*>& nodes)->AstNode* {
            return new IfStmnt(nodes.at(1), nodes.at(2), nodes.at(3));
        });
        
        Grammar* whileStatement = Grammar::grammar();
        whileStatement->sequence({ createKeyword("while"), expr, block }, [](const std::vector<AstNode*>& nodes)->AstNode* {
            return new WhileStmnt(nodes.at(1), nodes.at(2));
         });
        statement->o_r({ 
            ifStatement, 
            whileStatement, 
         simple });
        return statement;
    }

    Grammar* createLineEnd()
    {
        Grammar* lineEnd = Grammar::grammar();
        lineEnd = lineEnd->o_r({ createEoL(), createSeperator(";") });
        return lineEnd;
    }

    Grammar* createBlock(Grammar* block, Grammar* statement, Grammar* lineEnd)
    {
        Grammar *opt = Grammar::grammar()->option(statement);
        Grammar* rep = Grammar::grammar()->repeat(Grammar::grammar()->sequence({ lineEnd, opt }, [](const std::vector<AstNode*>& nodes)->AstNode* {
            if (nodes.size() < 2) {
                return nullptr;
            }
            return nodes.at(1);
        }));

        block = block->sequence({createSeperator("{"), opt, rep, createSeperator("}")}, [](const std::vector<AstNode*>& nodes)->AstNode* {
            if (nodes.size() == 2) 
            {
                return nullptr;
            }
            if (nodes.size() == 3) 
            {
                return nodes.at(1);
            }
            ListNode* lst = dynamic_cast<ListNode*>(nodes.at(2));
            lst->addChild(nodes.at(1));
            return lst;
        });
        return block;
    }

    Grammar* createProgram(Grammar* statement, Grammar* lineEnd)
    {
        Grammar* grammar = Grammar::grammar();
        Grammar* seq = Grammar::grammar()->sequence({ statement, lineEnd }, [](const std::vector<AstNode*>& nodes)->AstNode* {
            if (nodes.size() != 2) {
                return nullptr;
            }
            return nodes.at(0);
        });
        grammar = grammar->o_r({ seq, lineEnd });
        return grammar;
    }

    Grammar* createFactor(Grammar* primary)
    {
        Grammar* factor = Grammar::grammar();
        factor->o_r({ primary });
        return factor;
    }

    Grammar* createExpr(Grammar* expr, Grammar* factor)
    {
        Grammar* operateGrammar = Grammar::grammar();
        operateGrammar->sequence({ factor, createOperator({"==", ">", "<","=", "+", "-", "*", "/"}), factor }, [](const std::vector<AstNode*>& nodes)->AstNode* {

            OperatorNode* operatorNode = dynamic_cast<OperatorNode*>(nodes.at(1));
            BinaryExpr* binaryExpr = new BinaryExpr(
                operatorNode->getOperatorToken(),
                nodes.at(0),
                nodes.at(2)
            );
            operatorNode->setOperatorToken(nullptr);
            delete operatorNode;
            return binaryExpr;
            });
        expr->o_r({ operateGrammar, factor });
        return expr;
    }

    Grammar* createPrimary(Grammar* primary, Grammar* expr)
    {
        Grammar* grammar = Grammar::grammar();
        grammar->sequence({ createSeperator("("), expr, createSeperator(")") }, [](const std::vector<AstNode*>& nodes)->AstNode* {

            AstNode* left = nodes.at(0);
            AstNode* right = nodes.at(2);
            delete left;
            delete right;
            return nodes.at(1);
            });
        primary->o_r({ grammar, createNumber(), createIdentifier() });
        return primary;
    }
}
